package com.personal.core.utils;

import java.util.ArrayList;
import java.util.List;

import com.personal.core.bean.CountEntity;
import com.personal.core.port.HaveDeepAndChildren;

/**
 * 深度子节点工具类
 * @author cuibo
 *
 */
public final class DeepChildrenUtil
{
    
    /**
     * 获取叶子节点
     * @return
     */
    public static <T extends HaveDeepAndChildren> List<T> getLeafs(List<T> objs)
    {
        if (CoreUtil.isEmpty(objs))
        {
            return null;
        }
        List<T> result = new ArrayList<T>();
        List<T> singleResult = null;
        for (T t : objs)
        {
            singleResult = getLeafs(t);
            if (!CoreUtil.isEmpty(singleResult))
            {
                result.addAll(singleResult);
            }
        }
        return result;
    }
    
    /**
     * 获取叶子节点
     * @return
     */
    public static <T extends HaveDeepAndChildren> List<T> getLeafs(T obj)
    {
        List<T> result = new ArrayList<T>();
        if (obj.isLeaf())
        {
            result.add((T)obj);
            return result;
        } else
        {
            getLeafImpl(obj.getChildren(), result);
        }
        return result;
    }
    
    @SuppressWarnings("unchecked")
    private static <T extends HaveDeepAndChildren> void getLeafImpl(List<? extends HaveDeepAndChildren> children, List<T> result)
    {
        if (children == null || children.isEmpty())
        {
            return;
        }
        for (HaveDeepAndChildren haveDeepAndChildren : children)
        {
            if (haveDeepAndChildren.isLeaf())
            {
                result.add((T)haveDeepAndChildren);
            } else
            {
                getLeafImpl(haveDeepAndChildren.getChildren(), result);
            }
        }
    }
    
    /**
     * 递归获取子节点
     * @param obj
     * @return
     */
    public static <T extends HaveDeepAndChildren> List<T> recursionGetChildren(T obj)
    {
        if (obj == null || obj.getChildren() == null || obj.getChildren().isEmpty())
        {
            return null;
        }
        List<T> result = new ArrayList<T>();
        recursionGetChildrenImpl(result, obj.getChildren());
        return result;
    }
    
    
    @SuppressWarnings("unchecked")
    private static <T extends HaveDeepAndChildren> void recursionGetChildrenImpl(List<T> result, List<? extends HaveDeepAndChildren> children)
    {
        if (children == null || children.isEmpty())
        {
            return;
        }
        for (HaveDeepAndChildren haveDeepAndChildren : children)
        {
            result.add((T)haveDeepAndChildren);
            recursionGetChildrenImpl(result, haveDeepAndChildren.getChildren());
        }
    }
    
    /**
     * 在HaveDeepAndChildren自己没有深度值的情况下，获取最大深度
     * @param groupFields
     * @return
     */
    public static int getMaxDeepIfNoDeep(List<? extends HaveDeepAndChildren> deepAndChildrens)
    {
        if (CoreUtil.isEmpty(deepAndChildrens))
        {
            return 0;
        }
        CountEntity count = new CountEntity(0);
        CountEntity level = new CountEntity(0);
        getMaxDeepIfNoDeepImpl(deepAndChildrens, count, level);
        return count.getCount();
    }

    private static void getMaxDeepIfNoDeepImpl(List<? extends HaveDeepAndChildren> deepAndChildrens, CountEntity count, CountEntity level)
    {
        // 每有一层，就加1
        if (CoreUtil.isEmpty(deepAndChildrens))
        {
            return;
        }
        boolean thisAdd = false;
        for (HaveDeepAndChildren c : deepAndChildrens)
        {
            if (!thisAdd && count.getCount() == level.getCount())
            {
                count.add();
                thisAdd = true;
            }
            if (!c.isLeaf())
            {
                CountEntity temp = new CountEntity();
                temp.setCount(level.getCount());
                temp.add();
                getMaxDeepIfNoDeepImpl(c.getChildren(), count, temp);
            }
        }
    }

    /**
     * 获取最大深度
     * @param groupFields
     * @return
     */
    public static int getMaxDeep(List<? extends HaveDeepAndChildren> deepAndChildrens)
    {
        if (CoreUtil.isEmpty(deepAndChildrens))
        {
            return 0;
        }
        int result = -1;
        for (HaveDeepAndChildren dc : deepAndChildrens)
        {
            if (dc.getDeepLength() > result)
            {
                result = dc.getDeepLength();
            }
            // 子维度的深度跟定比上一级的维度深度大
            if (dc.getChildren() != null && dc.getChildren().size() > 0)
            {
                int tempResult = getMaxDeep(dc.getChildren());
                if (tempResult > result)
                {
                    result = tempResult;
                }
            }
        }
        return result;
    }
    
    /**
     * 获取指定深度下的所属数据
     * @param groupFields
     * @param deep
     * @return
     */
    public static <T extends HaveDeepAndChildren> List<T> getByDeep(List<T> deepAndChildrens, int deep)
    {
        if (deepAndChildrens == null || deepAndChildrens.isEmpty())
        {
            return null;
        }
        List<T> result = new ArrayList<T>();
        getByDeepImpl(deepAndChildrens, deep, result);
        return result;
    }
    
    @SuppressWarnings("unchecked")
    private static <T extends HaveDeepAndChildren> void getByDeepImpl(List<? extends HaveDeepAndChildren> deepAndChildrens,
            int deep, List<T> result)
    {
        if (deepAndChildrens == null || deepAndChildrens.isEmpty())
        {
            return;
        }
        for (HaveDeepAndChildren deepAndChildren : deepAndChildrens)
        {
            if (deep == deepAndChildren.getDeepLength())
            {
                result.add((T)deepAndChildren);
            }
            if (deepAndChildren.getChildren() != null && deepAndChildren.getChildren().size() > 0)
            {
                getByDeepImpl(deepAndChildren.getChildren(), deep, result);
            }
        }
    }

    /**
     * 递归设置深度
     * @param deepAndChildrens
     */
    public static void setDeepLength(List<? extends HaveDeepAndChildren> deepAndChildrens)
    {
        if (deepAndChildrens == null || deepAndChildrens.isEmpty())
        {
            return;
        }
        // 计数器计算深度值
        CountEntity countEntity = null;
        for (HaveDeepAndChildren deepAndChildren : deepAndChildrens)
        {
            countEntity = new CountEntity(1);
            deepAndChildren.setDeepLength(countEntity.getCount());
            if (deepAndChildren.getChildren() != null && deepAndChildren.getChildren().size() > 0)
            {
                // 计数器加1
                countEntity.add();
                setDeepLengthImpl(deepAndChildren.getChildren(), countEntity);
            }
        }
    }
    
    /**
     * 递归计算深度
     * @param deepAndChildrens
     * @param countEntity
     */
    private static void setDeepLengthImpl(List<? extends HaveDeepAndChildren> deepAndChildrens, CountEntity countEntity)
    {
        if (deepAndChildrens == null || deepAndChildrens.isEmpty())
        {
            return;
        }
        // 每次都要重新new一个计数器记录原计数器的值
        CountEntity tempCount = null;
        for (HaveDeepAndChildren deepAndChildren : deepAndChildrens)
        {
            deepAndChildren.setDeepLength(countEntity.getCount());
            if (deepAndChildren.getChildren() != null && !deepAndChildren.getChildren().isEmpty())
            {
                tempCount = new CountEntity();
                tempCount.setCount(countEntity.getCount());
                // 计数器加1
                tempCount.add();
                // 递归
                setDeepLengthImpl(deepAndChildren.getChildren(), tempCount);
            }
        }
    }
    
}
